#include "StdAfx.h"
#include"Storage.h"
#include"Executor.h"
#include"Validator.h"
#include"assert.h"

//@author A0104234X
using namespace std;

const string Storage::KEYWORD_DATE = " -date ";
const string Storage::KEYWORD_STARTS = " -starts ";
const string Storage::KEYWORD_ENDS = " -ends ";
const string Storage::KEYWORD_DETAIL = " -detail ";
const string Storage::KEYWORD_IMPT = " -impt ";
const string Storage::KEYWORD_DONE = " -done ";

const string Storage::STORE_FILE_NAME = "tasker.txt";
const string Storage::LOG_FILE_NAME = "logging.txt";

//vector<vector<Task*>> Storage::taskListStack;
vector<string> Storage::commandStack;

void Storage::storeResult(vector<Task *> tasklist){
	Validator checker;
	fstream storeFile;
	fstream logFile;
	try{
		storeFile.open(STORE_FILE_NAME,ios::out);
		if(!storeFile.is_open()){
			throw STORE_FILE_NAME;
		}
	}
	catch(string str){
		cout<<"error occurs when open "+str;
	}
	try
	{
		logFile.open(LOG_FILE_NAME,ios::app);
		if (!logFile.is_open())
		{
			throw LOG_FILE_NAME;
		}
	}
	catch(string str){
		cout<<"error occurs when open "+str;
	}
	
	logFile<<endl;
	for(int i=0;i<tasklist.size();i++)
	{
		string taskName = tasklist[i]->getName();
		string taskDate = tasklist[i]->getDate();
		int taskStart = tasklist[i]->getStartTime();
		int taskEnd = tasklist[i]->getEndTime();
		bool impt = tasklist[i]->getImpt();
		bool done = tasklist[i]->getDone();
		string detail = tasklist[i]->getDetail();

		storeFile<<taskName
			<<KEYWORD_DATE
			<<taskDate
			<<KEYWORD_STARTS
			<<taskStart
			<<KEYWORD_ENDS
			<<taskEnd
			<<KEYWORD_IMPT
			<<impt
			<<KEYWORD_DONE
			<<done
			<<KEYWORD_DETAIL
			<<detail
			<<endl;
		logFile<<taskName
			<<KEYWORD_DATE
			<<taskDate
			<<KEYWORD_STARTS
			<<taskStart
			<<KEYWORD_ENDS
			<<taskEnd
			<<KEYWORD_IMPT
			<<impt
			<<KEYWORD_DONE
			<<done
			<<KEYWORD_DETAIL
			<<detail
			<<endl;
	}
	storeFile.close();
	logFile.close();
}

vector<Task*> Storage::undo(){
	char buf[MAX_ARRAY][MAX_ARRAY];
	int start=0;
	int end=0;

	ifstream logFile;
	fstream storeFile;
	logFile.open(LOG_FILE_NAME,ios::in);
	int i=0;
	while(!logFile.eof() && (i < MAX_ARRAY)){
		logFile.getline(buf[i++],MAX_ARRAY);
	}
	int j=0;
	i=i-1;
	while(j<i){
		if(strlen(buf[j++])==0){
			start=end;
			end=j-1;;
		}
	}

	ostringstream outstr;
	storeFile.open(STORE_FILE_NAME,ios::out);
	for(int k=start+1;k<end;k++){
		if(k==end-1)
			outstr<<buf[k];
		else
			outstr<<buf[k]<<endl;
	}
	string linesForFile = outstr.str();
	storeFile<<linesForFile<<endl;
	storeFile.close();
	logFile.close();
	fstream logFileMo(LOG_FILE_NAME,ios::out);
	for(int k=0;k<end;k++){
		logFileMo<<buf[k]<<endl;
	}
	return loadVect();
}

void Storage::clearLog(){
	fstream clearLogFile(LOG_FILE_NAME,ios::out);
	fstream storeFile(STORE_FILE_NAME,ios::in);
	char buf[MAX_ARRAY][MAX_ARRAY];
	int i=0;
	while(!storeFile.eof())
	{
	
		storeFile.getline(buf[i++],MAX_ARRAY);
	}
	i=i-1;
	clearLogFile<<endl;
	for(int j=0;j<i;j++){
		clearLogFile<<buf[j]<<endl;
	}
	storeFile.close();
	clearLogFile.close();
	
	
	
}

#pragma region Alternate Implementation of loadVect that does not require Executor
vector<Task*> Storage::loadVect(){
	Validator checker;

	vector<Task*> tasklist;
	fstream fileStore;
	fileStore.open(STORE_FILE_NAME,ios::in);
	if(fileStore.fail())
		fileStore.open(STORE_FILE_NAME,ios::out);

	string oneTask;
	string holder;
	while(!checker.isFileEmpty(fileStore)) {
		getline(fileStore, oneTask);
		Task *t=new Task;
		holder = getTaskInfo(oneTask, "", KEYWORD_DATE);
		t->appendToName(holder);
		holder = getTaskInfo(oneTask, KEYWORD_DATE, KEYWORD_STARTS);
		t->setDate(holder);
		holder = getTaskInfo(oneTask, KEYWORD_STARTS, KEYWORD_ENDS);
		t->setStartTime(atoi(holder.c_str()));
		holder = getTaskInfo(oneTask, KEYWORD_ENDS, KEYWORD_DETAIL);
		t->setEndTime(atoi(holder.c_str()));
		holder = getTaskInfo(oneTask, KEYWORD_DETAIL, KEYWORD_IMPT);
		t->appendToDetail(holder);
		holder = getTaskInfo(oneTask, KEYWORD_IMPT, KEYWORD_DONE);
		t->setImpt((atoi(holder.c_str())==1));
		holder = getTaskInfo(oneTask, KEYWORD_DONE, "");
		t->setDone((atoi(holder.c_str())==1));
		tasklist.push_back(t);
	}
	return tasklist;
}

string Storage::getTaskInfo(string& task, string infoStart, string infoEnd)
{
	int startPos = 0, endPos = 0;
	if(!infoStart.empty())
	{
		startPos = task.find(infoStart);
		if(startPos == string::npos)
			return "";
		startPos += infoStart.length();
	}
	endPos = task.rfind(infoEnd);
	if(endPos == string::npos)
		return task.substr(startPos).c_str();
	return task.substr(startPos, endPos-startPos).c_str();
}

#pragma endregion


void Storage::saveCommand(string command)
{
	commandStack.push_back(command);
}

string Storage::undidCommand()
{
	string commandUndid;

	commandUndid = commandStack[commandStack.size()-1];

	if(commandStack[commandStack.size()-1] != "initial")
		commandStack.pop_back();
	
	return commandUndid;
}